package main

import (
	"encoding/json"
	"fmt"
	"net"
	"os"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	"github.com/spf13/pflag"
)

func main() {
	cfgFile := pflag.StringP("config", "c", "", "")
	pflag.Parse()
	if *cfgFile == "" {
		fmt.Printf("must provide config file")
		os.Exit(-1)
	}
	config, err := loadConfig(*cfgFile)
	if err != nil {
		panic(err)
	}
	conn, err := net.Dial(config.Dest.Network, config.Dest.Addr)
	if err != nil {
		panic(err)
	}

	// Echo instance
	e := echo.New()

	globalCache := cacheType{
		m: config.Aux,
	}

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())
	e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			cc := &Context{
				Context: c,
				conn:    conn,
				cache:   &globalCache,
			}
			return next(cc)
		}
	})

	// Routes
	e.POST(config.Path, formatNMEA2000)

	// Start server
	e.Logger.Fatal(e.Start(config.Listen))
}

type Context struct {
	echo.Context
	conn  net.Conn
	cache *cacheType
}

func (c *Context) SendData(data map[string]interface{}) {
	msg, err := json.Marshal(data)
	if err != nil {
		c.Logger().Error("failed marshal to json")
		return
	}
	n, err := c.conn.Write(msg)
	if err != nil {
		c.Logger().Errorf("failed send data err = %s", err)
		return
	}
	c.Logger().Infof("successfully send data len = %d", n)

}

func formatNMEA2000(c echo.Context) error {
	cc := c.(*Context)
	s := new(InfluxDBData)
	if err := c.Bind(&s); err != nil {
		return err
	}
	_ = c.NoContent(200)
	fmt.Printf("s = %+v\n", s)
	err := cc.cache.Parse(s)
	if err != nil {
		return err
	}
	fmt.Printf("data = %+v\n", cc.cache.m)
	if id, ok := cc.cache.m["id"]; ok {
		m := map[string]interface{}{}
		m["id"] = id
		m["data"] = cc.cache.m
		cc.SendData(m)
	}
	return nil
}

func merge(org map[string]interface{}, m map[string]interface{}) map[string]interface{} {
	d := map[string]interface{}{}
	for k, v := range org {
		d[k] = v
	}
	for k, v := range m {
		d[k] = v
	}
	return d
}
